﻿package com.rbac.system.service.impl;

import com.rbac.system.entity.Menu;
import com.rbac.system.entity.Permission;
import com.rbac.system.entity.RolePermission;
import com.rbac.system.mapper.MenuMapper;
import com.rbac.system.mapper.PermissionMapper;
import com.rbac.system.mapper.RolePermissionMapper;
import com.rbac.system.service.MenuPermissionMappingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单权限映射服务实现
 */
@Service
public class MenuPermissionMappingServiceImpl implements MenuPermissionMappingService {
    
    @Autowired
    private MenuMapper menuMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Override
    public Set<Long> getPermissionsByMenus(List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return new HashSet<>();
        }
        
        Set<Long> permissionIds = new HashSet<>();
        
        for (Long menuId : menuIds) {
            Menu menu = menuMapper.selectById(menuId);
            if (menu != null) {
                Set<String> permissionCodes = getPermissionCodesByMenu(menu);
                for (String permissionCode : permissionCodes) {
                    Permission permission = permissionMapper.selectByCode(permissionCode);
                    if (permission != null) {
                        permissionIds.add(permission.getId());
                    }
                }
            }
        }
        
        return permissionIds;
    }
    
    @Override
    public Set<String> getPermissionCodesByMenuCodes(List<String> menuCodes) {
        if (menuCodes == null || menuCodes.isEmpty()) {
            return new HashSet<>();
        }
        
        Set<String> permissionCodes = new HashSet<>();
        
        for (String menuCode : menuCodes) {
            permissionCodes.addAll(mapMenuCodeToPermissionCodes(menuCode));
        }
        
        return permissionCodes;
    }
    
    @Override
    public Set<String> getPermissionCodesByMenuPath(String menuPath) {
        if (menuPath == null || menuPath.isEmpty()) {
            return new HashSet<>();
        }
        
        return mapMenuPathToPermissionCodes(menuPath);
    }
    
    @Override
    @Transactional
    public int assignPermissionsForMenus(Long roleId, List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return 0;
        }
        
        Set<Long> permissionIds = getPermissionsByMenus(menuIds);
        int assignedCount = 0;
        
        // 获取角色已有的权限，避免重复分配
        List<RolePermission> existingRolePermissions = rolePermissionMapper.selectByRoleId(roleId);
        Set<Long> existingPermissionIds = existingRolePermissions.stream()
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toSet());
        
        for (Long permissionId : permissionIds) {
            if (!existingPermissionIds.contains(permissionId)) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                rolePermission.setCreateTime(LocalDateTime.now());
                rolePermission.setDeleted(0);
                rolePermissionMapper.insert(rolePermission);
                assignedCount++;
            }
        }
        
        return assignedCount;
    }
    
    /**
     * 根据菜单获取对应的权限编码
     */
    private Set<String> getPermissionCodesByMenu(Menu menu) {
        Set<String> permissionCodes = new HashSet<>();
        
        if (menu.getMenuCode() != null) {
            permissionCodes.addAll(mapMenuCodeToPermissionCodes(menu.getMenuCode()));
        }
        
        if (menu.getPath() != null) {
            permissionCodes.addAll(mapMenuPathToPermissionCodes(menu.getPath()));
        }
        
        return permissionCodes;
    }
    
    /**
     * 根据菜单编码映射到权限编码
     */
    private Set<String> mapMenuCodeToPermissionCodes(String menuCode) {
        Set<String> permissionCodes = new HashSet<>();

        // 首先查询数据库中实际存在的权限
        List<Permission> allPermissions = permissionMapper.selectList(new Permission());
        Set<String> existingPermissionCodes = allPermissions.stream()
                .map(Permission::getPermissionCode)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        // 根据菜单编码规则映射到权限编码，但只添加实际存在的权限
        Set<String> candidatePermissions = new HashSet<>();

        switch (menuCode.toLowerCase()) {
            case "profile":
            case "user-profile":
                candidatePermissions.add("user:profile:view");
                candidatePermissions.add("user:profile:edit");
                candidatePermissions.add("user:password:change");
                break;

            case "user-management":
            case "admin-user":
                candidatePermissions.add("admin:user:list");
                candidatePermissions.add("admin:user:view");
                candidatePermissions.add("admin:user:add");
                candidatePermissions.add("admin:user:update");
                candidatePermissions.add("admin:user:delete");
                candidatePermissions.add("admin:user:reset-password");
                break;

            case "role-management":
            case "admin-role":
                candidatePermissions.add("admin:role:list");
                candidatePermissions.add("admin:role:view");
                candidatePermissions.add("admin:role:add");
                candidatePermissions.add("admin:role:update");
                candidatePermissions.add("admin:role:delete");
                candidatePermissions.add("admin:role:assign-permission");
                candidatePermissions.add("admin:role:assign-menu");
                break;

            case "menu-management":
            case "admin-menu":
                candidatePermissions.add("admin:menu:list");
                candidatePermissions.add("admin:menu:view");
                candidatePermissions.add("admin:menu:add");
                candidatePermissions.add("admin:menu:update");
                candidatePermissions.add("admin:menu:delete");
                break;

            case "permission-management":
            case "admin-permission":
                candidatePermissions.add("admin:permission:list");
                candidatePermissions.add("admin:permission:view");
                candidatePermissions.add("admin:permission:add");
                candidatePermissions.add("admin:permission:update");
                candidatePermissions.add("admin:permission:delete");
                break;

            case "notice-management":
            case "通知管理":
                candidatePermissions.add("notice:list");
                candidatePermissions.add("notice:view");
                candidatePermissions.add("notice:add");
                candidatePermissions.add("notice:update");
                candidatePermissions.add("notice:delete");
                candidatePermissions.add("notice:publish");
                break;

            case "notice":
            case "通知公告":
                candidatePermissions.add("notice:list");
                candidatePermissions.add("notice:view");
                candidatePermissions.add("notice:add");
                candidatePermissions.add("notice:update");
                candidatePermissions.add("notice:delete");
                candidatePermissions.add("notice:publish");
                break;

            default:
                // 对于其他菜单，尝试根据命名规则推断
                if (menuCode.contains("user") || menuCode.contains("用户")) {
                    candidatePermissions.add("admin:user:view");
                    candidatePermissions.add("admin:user:list");
                } else if (menuCode.contains("role") || menuCode.contains("角色")) {
                    candidatePermissions.add("admin:role:view");
                    candidatePermissions.add("admin:role:list");
                } else if (menuCode.contains("menu") || menuCode.contains("菜单")) {
                    candidatePermissions.add("admin:menu:view");
                    candidatePermissions.add("admin:menu:list");
                } else if (menuCode.contains("permission") || menuCode.contains("权限")) {
                    candidatePermissions.add("admin:permission:view");
                    candidatePermissions.add("admin:permission:list");
                } else if (menuCode.contains("notice") || menuCode.contains("通知") || menuCode.contains("公告")) {
                    candidatePermissions.add("notice:list");
                    candidatePermissions.add("notice:view");
                }
                break;
        }

        // 只返回实际存在的权限
        for (String candidate : candidatePermissions) {
            if (existingPermissionCodes.contains(candidate)) {
                permissionCodes.add(candidate);
            }
        }

        return permissionCodes;
    }
    
    /**
     * 根据菜单路径映射到权限编码
     */
    private Set<String> mapMenuPathToPermissionCodes(String menuPath) {
        Set<String> permissionCodes = new HashSet<>();

        // 查询数据库中实际存在的权限
        List<Permission> allPermissions = permissionMapper.selectList(new Permission());
        Set<String> existingPermissionCodes = allPermissions.stream()
                .map(Permission::getPermissionCode)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        Set<String> candidatePermissions = new HashSet<>();

        // 根据菜单路径规则映射到权限编码
        if (menuPath.contains("/profile")) {
            candidatePermissions.add("user:profile:view");
            candidatePermissions.add("user:profile:edit");
            candidatePermissions.add("user:password:change");
        } else if (menuPath.contains("/system/user")) {
            candidatePermissions.add("admin:user:list");
            candidatePermissions.add("admin:user:view");
        } else if (menuPath.contains("/system/role")) {
            candidatePermissions.add("admin:role:list");
            candidatePermissions.add("admin:role:view");
        } else if (menuPath.contains("/system/menu")) {
            candidatePermissions.add("admin:menu:list");
            candidatePermissions.add("admin:menu:view");
        } else if (menuPath.contains("/system/permission")) {
            candidatePermissions.add("admin:permission:list");
            candidatePermissions.add("admin:permission:view");
        } else if (menuPath.contains("/notice") || menuPath.contains("/notification")) {
            candidatePermissions.add("notice:list");
            candidatePermissions.add("notice:view");
            candidatePermissions.add("notice:add");
            candidatePermissions.add("notice:update");
            candidatePermissions.add("notice:delete");
            candidatePermissions.add("notice:publish");
        }

        // 只返回实际存在的权限
        for (String candidate : candidatePermissions) {
            if (existingPermissionCodes.contains(candidate)) {
                permissionCodes.add(candidate);
            }
        }

        return permissionCodes;
    }
}


